package com.duke.shaking.interaction;

import org.json.JSONObject;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.graphics.drawable.BitmapDrawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Vibrator;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationSet;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.TextView;

import com.androidquery.AQuery;
import com.duke.shaking.BaseActivity;
import com.duke.shaking.R;
import com.duke.shaking.ResultCodeFactory;
import com.duke.shaking.ShakeTabActivity;
import com.duke.shaking.ShakeTabEvent;
import com.duke.shaking.more.VIPUpgradeActivity;
import com.duke.shaking.net.AsyncHttpResponseWithResultHandler;
import com.duke.shaking.net.NetUtils;
import com.duke.shaking.pojo.ChatFriend;
import com.duke.shaking.pojo.User;
import com.duke.shaking.profile.FriendPhotosActivity;
import com.duke.shaking.profile.FriendProfileActivity;
import com.duke.shaking.services.PopupUpdateAlertService;
import com.duke.shaking.utils.PrefUtils;


public class ShakeActivity extends BaseActivity 
	implements ShakeTabEvent, 
	AnimationListener,
	SensorEventListener {
	public static final int SHAKE_FILTER_ALL = 0;
	public static final int SHAKE_FILTER_FEMALE = 1;
	public static final int SHAKE_FILTER_MALE = 2;
	public static final int SHAKE_THRESHOLD = 800;
	public static final int SHAKE_DETECT_TIME = 100;
	private float shakeLastX = 0;
	private float shakeLastY = 0;
	private long shakeLastUpdateTime = 0;
	
	private final int animDuration = 300;
	private AQuery aQuery;
	private ChatFriend shakedFriend;
	private ShakeTabActivity tabsActivity;
	private boolean silence;
	private int filter;
	private LayoutInflater layoutFactory;
	private PopupWindow filterPop;
	private PrefUtils confPrefUtils;
	private ViewGroup layoutUp;
	private ViewGroup layoutDown;
	private AnimationSet upupAnimationSet;
	private AnimationSet updownAnimationSet;
	private AnimationSet downdownAnimationSet;
	private AnimationSet downupAnimationSet;
	private SensorManager sensorManager;
	private Vibrator vibrator;
	private boolean shaking;
	private MediaPlayer mediaPlayer;
	private MediaPlayer mediaPlayerGet;
	private MediaPlayer mediaPlayerFail;
	
	public void onCreate(Bundle savedInstanceState) {
		confPrefUtils = PrefUtils.getInstance(this, this.getString(R.string.configPref));
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shaking);
    	silence = confPrefUtils.getBoolean(getString(R.string.conf_shakeWithSilence), false);
    	filter = confPrefUtils.getInt(getString(R.string.conf_shakeFilter), filter);
    	shaking = false;
        aQuery = new AQuery(this);
        layoutFactory = LayoutInflater.from(this);
        
        sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        vibrator = (Vibrator)getSystemService(VIBRATOR_SERVICE);
	}
	
	public void onActive(ShakeTabActivity tabs) {
		info("ShakeActivity.onActive");
		tabsActivity = tabs;
		tabs.initTitle(0,
				0,
				ShakeTabActivity.TITLE_BTN_EXIST,
				R.string.filter,
				R.string.shake);
		
        if (tabs.btnLeft != null) {
        	if (!silence) {
        		tabs.btnLeft.setBackgroundResource(R.drawable.voice);
        	}
        	else {
        		tabs.btnLeft.setBackgroundResource(R.drawable.silence);
        	}
        	tabs.btnLeft.setVisibility(View.VISIBLE);
        	tabs.btnLeft.setText("");
        }
	}

	public void onLeftBtn() {
		// TODO Auto-generated method stub
    	silence = confPrefUtils.getBoolean(getString(R.string.conf_shakeWithSilence), false);
    	silence = !silence;
    	confPrefUtils.addBoolean(getString(R.string.conf_shakeWithSilence), silence);
    	if (tabsActivity != null) {
	    	if (!silence) {
	    		tabsActivity.btnLeft.setBackgroundResource(R.drawable.voice);
	    	}
	    	else {
	    		tabsActivity.btnLeft.setBackgroundResource(R.drawable.silence);
	    	}
    	}
	}

	public void onRightBtn() {
		// TODO Auto-generated method stub
		if (filterPop != null && filterPop.isShowing()) {
			return;
		}
		if (me.getLevel() != null && me.getLevel() > 0) {
			showFilterBox();
		}
		else {
			gotoBuyService(R.string.tip_shake_upgrade_to_vip2);
		}
	}

	public void onBackBtn() {
		// TODO Auto-generated method stub
		
	}
	
	private void showShaked(ChatFriend shaked, String location) {
		setContentView(R.layout.activity_shaked);
		ImageView img_avatar = (ImageView)findViewById(R.id.img_avatar);
		if (shaked.getAvatarUrl() != null && img_avatar != null) {
			aQuery.id(R.id.img_avatar).image(shaked.getAvatarUrl(), false, true, 0, R.drawable.blank_avatar);
		}
		
		TextView txt_nickname = (TextView)findViewById(R.id.txt_nickname);
		if (txt_nickname != null && shaked.getNickname() != null) {
			txt_nickname.setText(shaked.getNickname());
		}
		
		TextView txt_location = (TextView)findViewById(R.id.txt_location);
		if (txt_location != null && location != null) {
			txt_location.setText(location);
		}
		
		ImageView img_vip = (ImageView)findViewById(R.id.img_vip);
		if (img_vip != null) {
			if (shaked.getLevel() != null && shaked.getLevel() > 0) {
				if (shaked.getLevel() == User.level_vip_year) {
					img_vip.setImageResource(R.drawable.yearvipicon);
				}
				else {
					img_vip.setImageResource(R.drawable.vipicon);
				}
				img_vip.setVisibility(View.VISIBLE);
			}
			else {
				img_vip.setVisibility(View.INVISIBLE);
			}
		}
	}
	
	public void onSayHello(View v) {
		if (shakedFriend != null) {
			go(ChatActivity.class, "friend", shakedFriend);
		}
	}
	
	public void onFriendClick(View v) {
		if (shakedFriend != null) {
			Intent i = new Intent(this, FriendProfileActivity.class);
			i.putExtra("friend", shakedFriend);
			i.putExtra("isNewFriend", true);
	    	startActivity(i);
		}
	}
	
	public void onFriendAvatarClick(View v) {
		if (shakedFriend != null) {
			Intent i = new Intent(this, FriendPhotosActivity.class);
			i.putExtra("friend", shakedFriend);
			i.putExtra("isNewFriend", true);
	    	startActivity(i);
		}
	}
	
	private void playResultSound(boolean success) {
		if (silence) {
			return;
		}
		
		if (success) {
			if (mediaPlayerGet == null) {
				mediaPlayerGet = MediaPlayer.create(this, R.raw.shake_match);
			}
			mediaPlayerGet.start();
		}
		else {
			if (mediaPlayerFail == null) {
				mediaPlayerFail = MediaPlayer.create(this, R.raw.shake_nomatch);
			}
			mediaPlayerFail.start();
		}
	}
	
	public void findShakeFriend() {
		AsyncHttpResponseWithResultHandler responseHandler = new AsyncHttpResponseWithResultHandler(){
			
        	@Override
			public void onResultSuccess(String response) {
				// TODO Auto-generated method stub
        		//toast("shaking response: " + response);
        		
        		super.onResultSuccess(response);
        		shaking = false;
				/*PrefUtils.getInstance(activity, activity.getString(R.string.registerPref))
					.addString(activity.getString(R.string.verifyCode), secret)
					.commit();*/

				JSONObject bodyJson = this.getBody(response);
				if(bodyJson == null) {
					changeShakeStatus(false, R.string.tip_no_shaking_friend);
					playResultSound(false);
					return;
				}
				
				String userId = bodyJson.optString(NetUtils.USERID, null);
				if (userId == null) {
					changeShakeStatus(false, R.string.tip_no_shaking_friend);
					playResultSound(false);
					return;
				}
				ChatFriend shaked = new ChatFriend();
				shaked.setUserId(userId);
				shaked.setNickname(bodyJson.optString(NetUtils.NAME, ""));
				shaked.setLevel(bodyJson.optInt(NetUtils.LEVEL, 0));
				shaked.setAvatarUrl(bodyJson.optString(NetUtils.URL, null));
				String location = bodyJson.optString(NetUtils.CITY1, "");
				location += " " + bodyJson.optString(NetUtils.CITY2, "");
				
        		showShaked(shaked, location);
        		shakedFriend = shaked;
        		playResultSound(true);
        		//changeShakeStatus(false, 0);
			}

			@Override
			public void onResultFailure(String result) {
				// TODO Auto-generated method stub
				super.onResultFailure(result);
				shaking = false;
				playResultSound(false);
				changeShakeStatus(false, 0);
				if (ResultCodeFactory.REQUEST_TIMES_USED.equals(result)) {
					if (!PopupUpdateAlertService.isProfileCompleted(me)) {
						gotoCompleteProfile();
					}
					else {
						gotoBuyService(R.string.tip_shake_upgrade_to_vip);
					}
				}
				
				//toast("");
			}
			
			@Override
			public void onFailure(Throwable arg0, String arg1) {
				// TODO Auto-generated method stub
				super.onFailure(arg0, arg1);
				shaking = false;
				changeShakeStatus(false, R.string.err_shake_network_issues);
			}
        };
        
        
        //Map<String, String> params = new HashMap<String, String>();
        //params.put(NetUtils.JOB, String.valueOf());
        NetUtils.shaking(this, responseHandler, filter);
	}
	
	public void onShaking(View v) {
		if (shaking) {
			return;
		}
		shaking = true;
		vibrator.vibrate(100);
        shakingAnimation();
	}

	private void gotoCompleteProfile() {
		Builder builder = new Builder(this);
		builder.setMessage(R.string.tip_shake_complete_profile).setPositiveButton(R.string.btn_goto_fill, new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				if (tabsActivity != null) {
					tabsActivity.selectTabByTag(ShakeTabActivity.TAG_MYSELF);
				}
				dialog.dismiss();
			}
		});
		builder.setNegativeButton(R.string.cancel, new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
			}
		});
		
		AlertDialog alert = builder.create();
		alert.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        alert.show();
	}
	
	private void gotoBuyService(int msgId) {
		Builder builder = new Builder(this);
		builder.setMessage(msgId).setPositiveButton(R.string.btn_upgrade_now, new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				go(VIPUpgradeActivity.class);
				dialog.dismiss();
			}
		});
		builder.setNegativeButton(R.string.cancel, new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
			}
		});
		
		AlertDialog alert = builder.create();
		alert.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        alert.show();
	}

	private void showFilterBox() {
		DisplayMetrics dm = new DisplayMetrics();  
		getWindowManager().getDefaultDisplay().getMetrics(dm);
		View popView = layoutFactory.inflate(R.layout.popup_shake_filter, null);
		
		filterPop = new PopupWindow(popView, LayoutParams.MATCH_PARENT, (int)(240 * dm.density), false);
		filterPop.setBackgroundDrawable(new BitmapDrawable()); 
		filterPop.setOutsideTouchable(true); 
		View parent = findViewById(R.id.tabview_shake);
		int h = tabsActivity.getTabPanelHeight();
		if (h <= 0) {
			h = 83;
		}
		filterPop.showAtLocation(parent, Gravity.BOTTOM, 0, h);
	}
	
	public void onFilter(View v) {
		int filter = SHAKE_FILTER_ALL;
		int id = v.getId();
		switch(id) {
		case R.id.btn_all:
			filter = SHAKE_FILTER_ALL;
			break;
		case R.id.btn_only_female:
			filter = SHAKE_FILTER_FEMALE;
			break;
		case R.id.btn_only_male:
			filter = SHAKE_FILTER_MALE;
			break;
		}
		this.filter = filter;
		confPrefUtils.addInt(getString(R.string.conf_shakeFilter), filter);
		if (filterPop != null && filterPop.isShowing()) {
			filterPop.dismiss();
			filterPop = null;
		}
	}
	
	public void onFilterCancel(View v) {
		if (filterPop != null && filterPop.isShowing()) {
			filterPop.dismiss();
			filterPop = null;
		}
	}
	
	private void shakingAnimation() {
		setContentView(R.layout.activity_shaking);
		layoutUp = (ViewGroup)findViewById(R.id.layout_up);
		layoutDown = (ViewGroup)findViewById(R.id.layout_down);
		
		TranslateAnimation upTranslate = new TranslateAnimation(
				Animation.RELATIVE_TO_SELF,	0.0f, 
				Animation.RELATIVE_TO_SELF, 0.0f, 
				Animation.RELATIVE_TO_SELF, 0.0f, 
				Animation.RELATIVE_TO_SELF, -0.5f);
		upTranslate.setDuration(animDuration);
		upupAnimationSet = new AnimationSet(true);
		upupAnimationSet.addAnimation(upTranslate);
		upupAnimationSet.setAnimationListener(this);
		layoutUp.startAnimation(upupAnimationSet);
		
		TranslateAnimation downTranslate = new TranslateAnimation(
				Animation.RELATIVE_TO_SELF, 0.0f, 
				Animation.RELATIVE_TO_SELF, 0.0f, 
				Animation.RELATIVE_TO_SELF, 0.0f, 
				Animation.RELATIVE_TO_SELF, 0.5f);
		downTranslate.setDuration(animDuration);
		downdownAnimationSet = new AnimationSet(true);
		downdownAnimationSet.addAnimation(downTranslate);
		downdownAnimationSet.setAnimationListener(this);
		layoutDown.startAnimation(downdownAnimationSet);
		changeShakeStatus(false, 0);
		if (!silence) {
			if (mediaPlayer == null) {
				mediaPlayer = MediaPlayer.create(this, R.raw.shake_sound_male);
			}
			mediaPlayer.start();
		}
		
		/*
		View lineUp = (View)findViewById(R.id.line_up);
		View lineDown = (View)findViewById(R.id.line_down);
		if (lineUp != null) {
			lineUp.setVisibility(View.VISIBLE);
		}
		if (lineDown != null) {
			lineDown.setVisibility(View.VISIBLE);
		}*/
	}

	public void onAnimationEnd(Animation animation) {
		// TODO Auto-generated method stub
		if (animation == upupAnimationSet) {
			TranslateAnimation upTranslate = new TranslateAnimation(
					Animation.RELATIVE_TO_SELF, 0.0f, 
					Animation.RELATIVE_TO_SELF, 0.0f, 
					Animation.RELATIVE_TO_SELF, -0.5f, 
					Animation.RELATIVE_TO_SELF, 0.0f);
			upTranslate.setDuration(animDuration);
			updownAnimationSet = new AnimationSet(true);
			updownAnimationSet.addAnimation(upTranslate);
			updownAnimationSet.setAnimationListener(this);
			layoutUp.startAnimation(updownAnimationSet);
			upupAnimationSet = null;
		}
		else if (animation == downdownAnimationSet) {
			TranslateAnimation downTranslate = new TranslateAnimation(
					Animation.RELATIVE_TO_SELF, 0.0f, 
					Animation.RELATIVE_TO_SELF, 0.0f, 
					Animation.RELATIVE_TO_SELF, 0.5f, 
					Animation.RELATIVE_TO_SELF, 0.0f);
			downTranslate.setDuration(animDuration);
			downupAnimationSet = new AnimationSet(true);
			downupAnimationSet.addAnimation(downTranslate);
			downupAnimationSet.setAnimationListener(this);
			layoutDown.startAnimation(downupAnimationSet);
			downdownAnimationSet = null;
		}
		else if (animation == updownAnimationSet) {
			updownAnimationSet = null;
		}
		else if (animation == downupAnimationSet) {
			downupAnimationSet = null;
		}
		
		if (upupAnimationSet == null
			&& updownAnimationSet == null
			&& downdownAnimationSet == null
			&& downupAnimationSet == null) {
			/*View lineUp = (View)findViewById(R.id.line_up);
			View lineDown = (View)findViewById(R.id.line_down);
			if (lineUp != null) {
				lineUp.setVisibility(View.GONE);
			}
			if (lineDown != null) {
				lineDown.setVisibility(View.GONE);
			}*/
			changeShakeStatus(true, 0);
			findShakeFriend();
		}
	}

	private void setViewVisibilityById(int viewId, int visibility) {
		View v = findViewById(viewId);
		if (v != null) {
			v.setVisibility(visibility);
		}
	}
	
	private void changeShakeStatus(boolean isShaking, int stateMsgId) {
		if (isShaking) {
			stateMsgId = R.string.tip_shake_searching;
		}
		if (stateMsgId > 0) {
			TextView txt = (TextView)findViewById(R.id.txt_shake_searching);
			if (txt != null) {
				txt.setText(stateMsgId);
			}
		}
		if (isShaking) {
			setViewVisibilityById(R.id.progressBar1, View.VISIBLE);
			setViewVisibilityById(R.id.txt_shake_searching, View.VISIBLE);
			setViewVisibilityById(R.id.txt_shake_tip1, View.GONE);
			setViewVisibilityById(R.id.txt_shake_tip2, View.GONE);
		}
		else {
			setViewVisibilityById(R.id.progressBar1, View.GONE);
			if (stateMsgId > 0) {
				setViewVisibilityById(R.id.txt_shake_searching, View.VISIBLE);
				setViewVisibilityById(R.id.txt_shake_tip1, View.GONE);
				setViewVisibilityById(R.id.txt_shake_tip2, View.GONE);
			}
			else {
				setViewVisibilityById(R.id.txt_shake_searching, View.GONE);
				setViewVisibilityById(R.id.txt_shake_tip1, View.VISIBLE);
				setViewVisibilityById(R.id.txt_shake_tip2, View.VISIBLE);
			}
		}
		
	}
	
	public void onAnimationRepeat(Animation animation) {
		// TODO Auto-generated method stub
		
	}

	public void onAnimationStart(Animation animation) {
		// TODO Auto-generated method stub
		
	}

	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// TODO Auto-generated method stub
		
	}

	public void onSensorChanged(SensorEvent event) {
		// TODO Auto-generated method stub
		int sensorType = event.sensor.getType();
		float[] values = event.values;
		if (sensorType == Sensor.TYPE_ACCELEROMETER) {
			long curTime = System.currentTimeMillis();
			if ((curTime - shakeLastUpdateTime) > SHAKE_DETECT_TIME) {
                 long diffTime = (curTime - shakeLastUpdateTime);
                 
                 float x = values[SensorManager.DATA_X];
                 float y = values[SensorManager.DATA_Y];
                 float acceChangeRate = 0;
                 if(shakeLastUpdateTime > 0) {
                	 acceChangeRate = (Math.abs(x - shakeLastX)
                			 + Math.abs(y - shakeLastY)) / diffTime * 10000;
                 }

                 if (acceChangeRate > SHAKE_THRESHOLD) {
                	 onShaking(null);
                 }
                 shakeLastUpdateTime = curTime;
                 shakeLastX = x;
                 shakeLastY = y;
            }
			/* 
			info("shake sensor values: " + values[0] + ", " + values[1] + ", " + values[2]);
			if (Math.abs(values[0]) > 12 || Math.abs(values[1]) > 12 || Math.abs(values[2]) > 12){
				
				onShaking(null);
			}*/
		}
	}
	
	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		sensorManager.registerListener(this, 
				sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), 
				SensorManager.SENSOR_DELAY_NORMAL);
	}
	
	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		//sensorManager.unregisterListener(this);
		super.onStop(); 
	}
	
	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		sensorManager.unregisterListener(this);
		super.onPause();
	}
}
